package org.michaelbel.bottomsheet;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;
import org.michaelbel.bottomsheet.adapter.BottomListProvider;
import org.michaelbel.bottomsheet.adapter.EasyGridProvider;
import org.michaelbel.bottomsheet.util.AlphaUtil;
import org.michaelbel.bottomsheet.util.ResTUtil;
import org.michaelbel.bottomsheet.util.WindowUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import static ohos.agp.components.Component.TouchEventListener;
import static ohos.agp.components.Component.VISIBLE;

/**
 * 主要类
 */
public class BottomSheet extends CommonDialog {
    /**
     * Type
     */
    public static final int LIST = 1;

    /**
     * grid模式
     */
    public static final int GRID = 2;

    /**
     * FabBehavior 暂时无法实现FAB_SLIDE_UP
     */
    public static final int FAB_SLIDE_UP = 20;

    /**
     * FAB_SHOW_HIDE
     */
    public static final int FAB_SHOW_HIDE = 21;

    private boolean dividers;
    private boolean fullWidth = true;
    private boolean whiteTheme;
    private boolean titleTextMultiline;

    private int cellHeight;
    private int layoutHeight;
    private int itemSelector;
    private int dimmingValue = 0;

    private int contentType = LIST;
    private int fabBehavior = FAB_SHOW_HIDE;

    private int titleTextColor;
    private int backgroundColor;
    private int listgroundColor;
    private int iconColor;
    private int itemTextColor;

    private ComponentContainer customView;
    private Text titleTextView;
    private ListContainer listContainer;
    private ComponentContainer topContainer;

    private List<Element> ICONS = new ArrayList<>();
    private List<String> ITEMS = new ArrayList<>();

    private String titleText;
    private ArrayList<BottomSheetItem> bottomsheetItems = new ArrayList<>();

    private int animationDuration = 200;

    // 动画起始坐标
    private float startTranslationX = 0;
    private float startTranslationY = 0;
    private float endTranslationX = 0;
    private float endTranslationY = 0;
    private int oldWidth;
    private int oldHeight;

    private EventHandler handler = new EventHandler(EventRunner.getMainEventRunner());

    private BottomSheetClickListener onClickListener;
    private BottomSheetCallback bottomSheetCallback;

    private Context context;
    private DependentLayout bottomRoot;

    public BottomSheet(Context context, boolean focus) {
        super(context);
        this.context = context;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        init(context);
    }

    private void init(Context context) {
        initDef();
        initView();
        initListContainerData();

        setAlignment(LayoutAlignment.BOTTOM);
        setTransparent(true);
        setSize(WindowUtil.getWindowWdith(context), WindowUtil.getWindowHeight(context));
        setContentCustomComponent(topContainer);
        customView.setTouchEventListener(
                new TouchEventListener() {
                    @Override
                    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                        return true;
                    }
                });
        customView.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                    }
                });
    }

    private void initDef() {
        if (backgroundColor == 0) {
            backgroundColor = whiteTheme ? 0xFFFFFFFF : 0xFF424242;
        }

        if (listgroundColor == 0) {
            listgroundColor = whiteTheme ? 0xFF424242 : 0xFFFFFFFF;
        }

        if (titleTextColor == 0) {
            titleTextColor = whiteTheme ? 0x8A000000 : 0xB3FFFFFF;
        }

        if (itemTextColor == 0) {
            itemTextColor = whiteTheme ? 0xDE000000 : 0xFFFFFFFF;
        }

        if (iconColor == 0) {
            iconColor = whiteTheme ? 0xFFFFFFFF : 0x8A000000;
        }

        if (cellHeight == 0) {
            cellHeight = AttrHelper.vp2px(48, context);
        }
    }

    private void initView() {
        topContainer =
                (ComponentContainer)
                        LayoutScatter.getInstance(context).parse(ResourceTable.Layout_bottom_sheet_layout, null, false);

        topContainer.setTranslationY(0);
        if (dimmingValue != 0) {
            topContainer.setBackground(ResTUtil.buildDrawableByColor(AlphaUtil.valueToColor(dimmingValue)));
        } else {
            topContainer.setBackground(ResTUtil.buildDrawableByColor(0x00000000));
        }

        customView = (ComponentContainer) topContainer.findComponentById(ResourceTable.Id_root_top);
        bottomRoot = (DependentLayout) topContainer.findComponentById(ResourceTable.Id_bottom_root);
        customView.setBackground(ResTUtil.buildDrawableByColor(backgroundColor));

        if (!fullWidth) {
            if (WindowUtil.getWindowWdith(context) > WindowUtil.getWindowHeight(context)) {
                int margin = WindowUtil.getWindowWdith(context) / 8;
                customView.setMarginLeft(margin);
                customView.setMarginRight(margin);
            }
        }

        if (titleText != null) {
            titleTextView = (Text) topContainer.findComponentById(ResourceTable.Id_txt_title);
            titleTextView.setVisibility(VISIBLE);
            titleTextView.setText(titleText);
            titleTextView.setTextColor(new Color(titleTextColor));
            titleTextView.setTextSize(AttrHelper.fp2px(16, context));
            titleTextView.setMultipleLine(titleTextMultiline);
        }

        listContainer = (ListContainer) topContainer.findComponentById(ResourceTable.Id_listContainer);
        listContainer.setBackground(ResTUtil.buildDrawableByColor(backgroundColor));
        if (!ITEMS.isEmpty()) {
            for (int a = 0; a < ITEMS.size(); a++) {
                bottomsheetItems.add(new BottomSheetItem(ITEMS.get(a), !ICONS.isEmpty() ? ICONS.get(a) : null));
            }
        }
    }

    private void initListContainerData() {
        if (contentType == LIST) {
            BottomListProvider bottomListProvider =
                    new BottomListProvider(context, itemTextColor, dividers, whiteTheme, cellHeight);
            bottomListProvider.setItemData(bottomsheetItems);
            listContainer.setItemProvider(bottomListProvider);
            listContainer.setItemClickedListener(
                    new ListContainer.ItemClickedListener() {
                        @Override
                        public void onItemClicked(ListContainer listContainer, Component component, int i1, long l1) {
                            onClickListener.onClickListener(i1, bottomsheetItems.get(i1).text);
                            handler.postTask(taskEnd);
                        }
                    });
            bottomListProvider.notifyDataChanged();
        } else {
            // 创建适配器
            EasyGridProvider easyGridProvider =
                    new EasyGridProvider<BottomSheetItem>(
                            context, ResourceTable.Layout_provider_grid_item, bottomsheetItems, whiteTheme) {
                        @Override
                        protected void bind(ViewHolder holder, BottomSheetItem item, int position) {
                            // 在这里做你想给每一个条目做的逻辑
                            // 设置文本的两种方式，目前只有Text支持第一种方式
                            holder.setText(ResourceTable.Id_txt_item, item.text);
                            holder.setTextColor(ResourceTable.Id_txt_item, new Color(itemTextColor));
                            holder.setImg(ResourceTable.Id_img_icon, item.icon);
                            holder.setBackGroundColor(
                                    ResourceTable.Id_dl_grid_root, ResTUtil.buildDrawableByColor(backgroundColor));
                        }
                    };
            // 设置列数
            easyGridProvider.setNumColumns(3);
            // 设置条目点击事件
            easyGridProvider.setOnItemClickListener(
                    new EasyGridProvider.OnItemClickListener() {
                        @Override
                        public void onItemClick(Component component, int position) {
                            onClickListener.onClickListener(position, bottomsheetItems.get(position).text);
                            handler.postTask(taskEnd);
                        }
                    });
            // 把适配器设置给ListContainer控件
            listContainer.setItemProvider(easyGridProvider);
        }
        topContainer.setClickedListener(
                new Component.ClickedListener() {
                    @Override
                    public void onClick(Component component) {
                        handler.postTask(taskEnd);
                    }
                });
    }

    private void setAnimator(final Component targetView) {
        endTranslationY = targetView.getTop();
        targetView.setTranslationY(((Component) targetView.getComponentParent()).getHeight() - targetView.getTop());
        startTranslationY = ((Component) targetView.getComponentParent()).getHeight();
        AnimatorValue animator = new AnimatorValue();

        animator.setDuration(animationDuration);
        animator.setCurveType(Animator.CurveType.ACCELERATE_DECELERATE);
        animator.setValueUpdateListener(
                new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float value) {
                        targetView.setTranslation(
                                (1 - value) * (startTranslationX - endTranslationX),
                                (1 - value) * (startTranslationY - endTranslationY));
                    }
                });
        animator.setStateChangedListener(
                new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {
                    }

                    @Override
                    public void onStop(Animator animator) {
                    }

                    @Override
                    public void onCancel(Animator animator) {
                    }

                    @Override
                    public void onEnd(Animator animator) {
                        oldHeight = customView.getHeight();
                    }

                    @Override
                    public void onPause(Animator animator) {
                    }

                    @Override
                    public void onResume(Animator animator) {
                    }
                });
        animator.start();
    }

    @Override
    protected void onShow() {
        super.onShow();
        handler.postTask(taskRunStart);
        if (bottomSheetCallback != null) {
            bottomSheetCallback.onShown();
        }
    }

    /**
     * 手机返回键手动调用动画
     */
    public void onBackPassedEvent() {
        handler.postTask(taskEnd);
    }

    @Override
    protected void onHide() {
        super.onHide();
    }

    @Override
    public void destroy() {
        if (bottomSheetCallback != null) {
            bottomSheetCallback.onDismissed();
        }

        super.destroy();
        handler.removeTask(taskRunStart);
        handler.removeTask(taskEnd);
    }

    private Runnable taskRunStart =
            new Runnable() {
                @Override
                public void run() {
                    if (customView != null) {
                        setAnimator(customView);
                    }
                }
            };

    private Runnable taskEnd =
            new Runnable() {
                @Override
                public void run() {
                    if (customView != null) {
                        endTranslationY += customView.getHeight() - oldHeight;
                        customView
                                .createAnimatorProperty()
                                .moveFromY(endTranslationY)
                                .moveToY(startTranslationY)
                                .setDuration(animationDuration)
                                .setStateChangedListener(
                                        new Animator.StateChangedListener() {
                                            @Override
                                            public void onStart(Animator animator) {
                                            }

                                            @Override
                                            public void onStop(Animator animator) {
                                            }

                                            @Override
                                            public void onCancel(Animator animator) {
                                            }

                                            @Override
                                            public void onEnd(Animator animator) {
                                                hide();
                                                destroy();
                                            }

                                            @Override
                                            public void onPause(Animator animator) {
                                            }

                                            @Override
                                            public void onResume(Animator animator) {
                                            }
                                        })
                                .start();
                    }
                }
            };

    /**
     * Builder
     */
    public static class Builder {
        private Context context;
        private BottomSheet bottomSheet;

        public Builder(Context context) {
            this.context = context;
            bottomSheet = new BottomSheet(context, false);
        }

        public Builder(Context context, boolean focus) {
            this.context = context;
            bottomSheet = new BottomSheet(context, focus);
        }

        public Builder(Context context, int focus) {
            this.context = context;
            bottomSheet = new BottomSheet(context, ResTUtil.getBoolean(context, focus));
        }

        /**
         * 设置title
         *
         * @param titleId titleId
         * @return Builder
         */
        public Builder setTitle(int titleId) {
            bottomSheet.titleText = ResTUtil.getString(context, titleId);
            return this;
        }

        /**
         * setTitle
         *
         * @param title title
         * @return Builder
         */
        public Builder setTitle(String title) {
            bottomSheet.titleText = title;
            return this;
        }

        /**
         * setItems
         *
         * @param items    items
         * @param listener listener
         * @return Builder
         */
        public Builder setItems(int[] items, final BottomSheetClickListener listener) {
            for (int i1 : items) {
                bottomSheet.ITEMS.add(ResTUtil.getString(context, i1));
            }
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * setItems
         *
         * @param items    items
         * @param listener listener
         * @return Builder
         */
        public Builder setItems(String[] items, final BottomSheetClickListener listener) {
            bottomSheet.ITEMS.addAll(Arrays.asList(items));
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * 设置Vector矢量图标
         *
         * @param items    items
         * @param icons    icons
         * @param listener listener
         * @return Builder
         */
        public Builder setItemsVectorIcons(int[] items, Element[] icons, final BottomSheetClickListener listener) {
            for (int i1 : items) {
                bottomSheet.ITEMS.add(ResTUtil.getString(context, i1));
            }
            for (Element j1 : icons) {
                bottomSheet.ICONS.add(j1);
            }
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * setItemsVectorIcons
         *
         * @param items    items
         * @param icons    icons 矢量图片资源
         * @param listener listener
         * @return Builder
         */
        public Builder setItemsVectorIcons(int[] items, int[] icons, final BottomSheetClickListener listener) {
            for (int i1 : items) {
                bottomSheet.ITEMS.add(ResTUtil.getString(context, i1));
            }
            for (int j1 : icons) {
                bottomSheet.ICONS.add(ResTUtil.getVectorDrawable(context, j1));
            }
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * setItems 普通图标
         *
         * @param items    items
         * @param icons    icons
         * @param listener listener
         * @return Builder
         */
        public Builder setItems(int[] items, Element[] icons, final BottomSheetClickListener listener) {
            for (int i1 : items) {
                bottomSheet.ITEMS.add(ResTUtil.getString(context, i1));
            }
            Collections.addAll(bottomSheet.ICONS, icons);
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * setItems
         *
         * @param items    items
         * @param icons    icons
         * @param listener listener
         * @return Builder
         */
        public Builder setItems(String[] items, int[] icons, final BottomSheetClickListener listener) {
            bottomSheet.ITEMS.addAll(Arrays.asList(items));
            for (int i1 : icons) {
                bottomSheet.ICONS.add(ResTUtil.getPixelMapDrawable(context, i1));
            }
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * setItems
         *
         * @param items    items
         * @param icons    icons
         * @param listener listener
         * @return Builder
         */
        public Builder setItems(int[] items, int[] icons, final BottomSheetClickListener listener) {
            for (int i1 : items) {
                bottomSheet.ITEMS.add(ResTUtil.getString(context, i1));
            }
            for (int i1 : icons) {
                bottomSheet.ICONS.add(ResTUtil.getPixelMapDrawable(context, i1));
            }
            bottomSheet.onClickListener = listener;
            return this;
        }

        /**
         * 可自定义面板
         *
         * @param layoutResId layoutResId
         * @return Builder
         */
        public Builder setView(int layoutResId) {
            bottomSheet.customView =
                    (ComponentContainer) LayoutScatter.getInstance(context).parse(layoutResId, null, false);
            return this;
        }

        /**
         * 自定义面板view
         *
         * @param view view
         * @return Builder
         */
        public Builder setView(Component view) {
            bottomSheet.customView = (ComponentContainer) view;
            return this;
        }

        // ----- Styles -------------------------------------------------------------------------------------

        /**
         * 设置列表类型
         *
         * @param type list grid两种类型
         * @return Builder
         */
        public Builder setContentType(int type) {
            bottomSheet.contentType = type;
            return this;
        }

        /**
         * 设置是否启动黑色主题
         *
         * @param theme theme
         * @return Builder
         */
        public Builder setDarkTheme(boolean theme) {
            bottomSheet.whiteTheme = theme;
            return this;
        }

        /**
         * 设置是否主题
         *
         * @param theme boolean类型资源
         * @return Builder
         */
        public Builder setDarkTheme(int theme) {
            bottomSheet.whiteTheme = ResTUtil.getBoolean(context, theme);
            return this;
        }

        /**
         * 设置是否横屏时充满屏幕
         *
         * @param fullWidth fullWidth
         * @return Builder
         */
        public Builder setFullWidth(boolean fullWidth) {
            bottomSheet.fullWidth = fullWidth;
            return this;
        }

        /**
         * setFullWidth
         *
         * @param fullWidth fullWidth
         * @return Builder
         */
        public Builder setFullWidth(int fullWidth) {
            bottomSheet.fullWidth = ResTUtil.getBoolean(context, fullWidth);
            return this;
        }

        /**
         * setCellHeight设置没栏高度
         *
         * @param cellHeight cellHeight
         * @return Builder
         */
        public Builder setCellHeight(int cellHeight) {
            bottomSheet.cellHeight = AttrHelper.vp2px(cellHeight, context);
            return this;
        }

        /**
         * 设置是否list有分界线
         *
         * @param dividers dividers
         * @return Builder
         */
        public Builder setDividers(boolean dividers) {
            bottomSheet.dividers = dividers;
            return this;
        }

        /**
         * setDividers
         *
         * @param dividers dividers
         * @return Builder
         */
        public Builder setDividers(int dividers) {
            bottomSheet.dividers = ResTUtil.getBoolean(context, dividers);
            return this;
        }

        /**
         * 设置背景窗口颜色
         *
         * @param windowDimming windowDimming
         * @return Builder
         */
        public Builder setWindowDimming(int windowDimming) {
            bottomSheet.dimmingValue = windowDimming;
            return this;
        }

        /**
         * 设置title是否可换行
         *
         * @param titleMultiline titleMultiline
         * @return Builder
         */
        public Builder setTitleMultiline(boolean titleMultiline) {
            bottomSheet.titleTextMultiline = titleMultiline;
            return this;
        }

        /**
         * setTitleMultiline
         *
         * @param titleMultiline titleMultiline
         * @return Builder
         */
        public Builder setTitleMultiline(int titleMultiline) {
            bottomSheet.titleTextMultiline = ResTUtil.getBoolean(context, titleMultiline);
            return this;
        }

        // ----- Colors -------------------------------------------------------------------------------------

        /**
         * 设置背景色
         *
         * @param backgroundColor backgroundColor
         * @return Builder
         */
        public Builder setBackgroundColor(int backgroundColor) {
            bottomSheet.backgroundColor = backgroundColor;
            return this;
        }

        /**
         * 设置背景色
         *
         * @param backgroundColorRes backgroundColorRes
         * @return Builder
         */
        public Builder setBackgroundColorRes(int backgroundColorRes) {
            bottomSheet.backgroundColor = ResTUtil.getColor(context, backgroundColorRes);
            return this;
        }

        /**
         * 设置setTitleTextColor
         *
         * @param titleTextColor titleTextColor
         * @return Builder
         */
        public Builder setTitleTextColor(int titleTextColor) {
            bottomSheet.titleTextColor = titleTextColor;
            return this;
        }

        /**
         * setTitleTextColorRes
         *
         * @param titleTextColorRes titleTextColorRes
         * @return Builder
         */
        public Builder setTitleTextColorRes(int titleTextColorRes) {
            bottomSheet.titleTextColor = ResTUtil.getColor(context, titleTextColorRes);
            return this;
        }

        /**
         * setItemTextColor
         *
         * @param itemTextColor itemTextColor
         * @return Builder
         */
        public Builder setItemTextColor(int itemTextColor) {
            bottomSheet.itemTextColor = itemTextColor;
            return this;
        }

        /**
         * setItemTextColorRes
         *
         * @param itemTextColorRes itemTextColorRes
         * @return Builder
         */
        public Builder setItemTextColorRes(int itemTextColorRes) {
            bottomSheet.itemTextColor = ResTUtil.getColor(context, itemTextColorRes);
            return this;
        }

        // ----- Interfaces ---------------------------------------------------------------------------------

        /**
         * 回调监听
         *
         * @param callback callback
         * @return Builder
         */
        public Builder setCallback(BottomSheetCallback callback) {
            bottomSheet.bottomSheetCallback = callback;
            return this;
        }

        // ----- Build --------------------------------------------------------------------------------------

        /**
         * 展示
         *
         * @return BottomSheet
         */
        public BottomSheet show() {
            bottomSheet.show();
            return bottomSheet;
        }

        /**
         * 关闭
         *
         * @return BottomSheet
         */
        public BottomSheet dismiss() {
            bottomSheet.hide();
            return bottomSheet;
        }

        /**
         * 获取BottomSheet
         *
         * @return BottomSheet
         */
        public BottomSheet create() {
            return bottomSheet;
        }

        // ----- Getters ------------------------------------------------------------------------------------

        /**
         * 获取title View
         *
         * @return Text
         */
        public Text getTitleTextView() {
            return bottomSheet.titleTextView;
        }

        /**
         * 获取listVeiw
         *
         * @return ListContainer
         */
        public ListContainer getListView() {
            return bottomSheet.listContainer;
        }

        /**
         * 获取面板 vieW
         *
         * @return Component
         */
        public Component getView() {
            return bottomSheet.customView;
        }
    }
}
